package com.mojian.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.mojian.common.RedisConstants;
import com.mojian.entity.SysArticle;
import com.mojian.entity.SysCategory;
import com.mojian.entity.SysNotifications;
import com.mojian.service.ArticleService;
import com.mojian.utils.IpUtil;
import com.mojian.utils.NotificationsUtil;
import com.mojian.utils.RedisUtil;
import com.mojian.vo.article.ArchiveListVo;
import com.mojian.vo.article.ArticleDetailVo;
import com.mojian.vo.article.ArticleListVo;
import com.mojian.vo.article.CategoryListVo;
import com.mojian.mapper.SysArticleMapper;
import com.mojian.mapper.SysCategoryMapper;
import com.mojian.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ArticleServiceImpl implements ArticleService {

    private final SysArticleMapper sysArticleMapper;

    private final SysCategoryMapper sysCategoryMapper;

    private final RedisUtil redisUtil;

    private final NotificationsUtil notificationsUtil;

    private final JdbcTemplate jdbcTemplate;

    private static final Logger log = LoggerFactory.getLogger(ArticleServiceImpl.class);

    @Override
    public IPage<ArticleListVo> getArticleList(Integer tagId, Integer categoryId, String keyword) {
        return sysArticleMapper.getArticleListApi(PageUtil.getPage(), tagId, categoryId, keyword);
    }

    @Override
    public ArticleDetailVo getArticleDetail(Long id) {
        ArticleDetailVo detailVo = sysArticleMapper.getArticleDetail(id);
        
        // 判断是否点赞和检查访问权限
        Object userIdObj = StpUtil.getLoginIdDefaultNull();
        if (userIdObj != null) {
            Long userId = Long.parseLong(userIdObj.toString());
            detailVo.setIsLike(sysArticleMapper.getUserIsLike(id, userId.intValue()));
            
            // 如果是会员专享内容(read_type=2)，检查会员权限
            if (detailVo != null && detailVo.getReadType() == 2) {
                log.info("文章[{}]是会员专享内容，检查用户[{}]的会员权限", id, userId);
                
                try {
                    // 检查是否有会员访问权限
                    Integer hasAccess = sysArticleMapper.checkMemberArticleAccess(userId, id);
                    log.info("用户[{}]访问会员专享文章[{}]的权限检查结果: {}", userId, id, hasAccess);
                    
                    if (hasAccess != null && hasAccess > 0) {
                        // 有会员访问权限，临时将文章类型设置为免费，允许前端显示
                        log.info("会员用户[{}]有权限访问会员专享文章[{}]", userId, id);
                        detailVo.setReadType(1);
                    } else {
                        log.info("用户[{}]无会员权限访问会员专享文章[{}]", userId, id);
                        
                        // 再验证一下用户是否是会员
                        String checkMemberSql = "SELECT COUNT(*) FROM member_user WHERE user_id = ? AND expire_time > NOW()";
                        Integer isMember = jdbcTemplate.queryForObject(checkMemberSql, Integer.class, userId);
                        log.info("用户[{}]会员状态检查结果: {}", userId, isMember);
                        
                        if (isMember != null && isMember > 0) {
                            // 用户是会员但没有访问权限记录，尝试手动添加
                            log.info("用户[{}]是有效会员但缺少文章[{}]的访问权限记录，尝试添加", userId, id);
                            
                            String addAccessSql = 
                                "INSERT INTO member_article_access (user_id, article_id, expire_time, create_time) " +
                                "SELECT ?, ?, expire_time, NOW() FROM member_user WHERE user_id = ? " +
                                "ON DUPLICATE KEY UPDATE expire_time = (SELECT expire_time FROM member_user WHERE user_id = ?)";
                                
                            jdbcTemplate.update(addAccessSql, userId, id, userId, userId);
                            
                            // 修改当前请求的文章类型为免费
                            detailVo.setReadType(1);
                            log.info("已为会员[{}]添加文章[{}]的访问权限并设置为可访问", userId, id);
                        }
                    }
                } catch (Exception e) {
                    log.error("检查会员权限时发生异常", e);
                }
            }
        }

        //添加阅读量
        String ip = IpUtil.getIp();
        ThreadUtil.execAsync(() -> {
            Map<Object, Object> map = redisUtil.hGetAll(RedisConstants.ARTICLE_QUANTITY);
            List<String> ipList = (List<String>) map.get(id.toString());
            if (ipList != null) {
                if (!ipList.contains(ip)) {
                    ipList.add(ip);
                }
            } else {
                ipList = new ArrayList<>();
                ipList.add(ip);
            }
            map.put(id.toString(), ipList);
            redisUtil.hSetAll(RedisConstants.ARTICLE_QUANTITY, map);
        });
        return detailVo;
    }

    @Override
    public List<ArchiveListVo> getArticleArchive() {

        List<ArchiveListVo> list = new ArrayList<>();

        List<Integer> years = sysArticleMapper.getArticleArchive();
        for (Integer year : years) {
            List<ArticleListVo> articleListVos = sysArticleMapper.getArticleByYear(year);
            list.add(new ArchiveListVo(year, articleListVos));
        }
        return list;
    }

    @Override
    public List<CategoryListVo> getArticleCategories() {
        return sysCategoryMapper.getArticleCategories();
    }

    @Override
    public List<ArticleListVo> getCarouselArticle() {
        return getArticlesByCondition(SysArticle::getIsCarousel);
    }

    @Override
    public List<ArticleListVo> getRecommendArticle() {
        return getArticlesByCondition(SysArticle::getIsRecommend);
    }

    @Override
    public Boolean like(Long articleId) {
        // 判断是否点赞
        int userId = StpUtil.getLoginIdAsInt();
        Boolean isLike = sysArticleMapper.getUserIsLike(articleId, userId);
        if (isLike) {
            // 点过则取消点赞
            sysArticleMapper.unLike(articleId, userId);
        } else {
            sysArticleMapper.like(articleId, userId);
            ThreadUtil.execAsync(() -> {
                //发送通知事件
                SysNotifications notifications = SysNotifications.builder()
                        .title("文章点赞通知")
                        .articleId(articleId)
                        .isRead(0)
                        .type("like")
                        .fromUserId(StpUtil.getLoginIdAsLong())
                        .build();
                notificationsUtil.publish(notifications);
            });
        }
        return true;
    }

    @Override
    public List<SysCategory> getCategoryAll() {
        return sysCategoryMapper.selectList(new LambdaQueryWrapper<SysCategory>()
                .orderByAsc(SysCategory::getSort));
    }

    private List<ArticleListVo> getArticlesByCondition(SFunction<SysArticle, Object> conditionField) {
        LambdaQueryWrapper<SysArticle> wrapper = new LambdaQueryWrapper<SysArticle>()
                .select(SysArticle::getId, SysArticle::getTitle, SysArticle::getCover, SysArticle::getCreateTime)
                .orderByDesc(SysArticle::getCreateTime)
                .eq(conditionField, 1);

        List<SysArticle> sysArticles = sysArticleMapper.selectList(wrapper);

        if (sysArticles == null || sysArticles.isEmpty()) {
            return Collections.emptyList();
        }

        return sysArticles.stream().map(item -> ArticleListVo.builder()
                .id(item.getId())
                .cover(item.getCover())
                .title(item.getTitle())
                .createTime(item.getCreateTime())
                .build()).collect(Collectors.toList());
    }

    @Override
    public boolean checkArticlePaid(Long userId, Long articleId) {
        if (userId == null || articleId == null) {
            return false;
        }
        
        log.info("检查用户[{}]是否已支付文章[{}]", userId, articleId);
        
        try {
            // 这里需要查询支付订单表，由于ArticleService中没有直接访问PayOrder的权限
            // 可以通过数据库查询或调用其他服务来实现
            // 这里使用直接SQL查询的方式
            Integer count = sysArticleMapper.checkArticlePaid(userId, articleId);
            boolean isPaid = count != null && count > 0;
            
            log.info("用户[{}]支付文章[{}]状态: {}", userId, articleId, isPaid ? "已支付" : "未支付");
            return isPaid;
        } catch (Exception e) {
            log.error("检查文章支付状态异常", e);
            return false;
        }
    }
}
